package cc.rengu.igas.opms.core.service.trans.apppay;


import cc.rengu.chargecalc.mchntfee.CalcMchntFee;
import cc.rengu.chargecalc.mchntfee.enums.CalcFlagEnum;
import cc.rengu.igas.share.common.enums.SettleAcctTypeEnum;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeResultBean;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeBean;
import cc.rengu.igas.acct.facade.bean.MchtAdjustDetail;
import cc.rengu.igas.acct.facade.request.VirtAcctMultiMchntAdjustRequest;
import cc.rengu.igas.momp.facade.base.Header;
import cc.rengu.igas.momp.facade.bean.PaymentOrderCouponInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentResponse;
import cc.rengu.igas.momp.facade.result.Result;
import cc.rengu.igas.opms.common.constant.OpmsServiceConstant;
import cc.rengu.igas.opms.common.constant.OpmsTreeNodeConstant;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.entity.*;
import cc.rengu.igas.opms.common.enums.CardTypeEnum;
import cc.rengu.igas.opms.common.enums.FeeTypeEnum;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.PayService;
import cc.rengu.igas.opms.facade.bean.PayInfo;
import cc.rengu.igas.opms.facade.request.MixedPayRequest;
import cc.rengu.igas.opms.facade.response.MobileBankScanPayResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntAcctInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.CsmcService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.CsmcServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderDetailMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderDetailMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.*;
import cc.rengu.oltp.service.realize.impl.BinInfoServiceImpl;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 手机银行扫码银行卡+积分快捷支付
 * Created by fyp on 2020/3/30.
 * modify by wangcheng 2021-09-13
 */
public class MobileBankScanCardScorePayService extends PayService implements TransCustomImpl {
    @Override
    protected Object bizBeforeCust() throws Exception {
        MixedPayRequest mixedPayRequest = new MixedPayRequest();
        ConvertUtil.convertOutput(mixedPayRequest);
        return mixedPayRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        MixedPayRequest mixedPayRequest = (MixedPayRequest) request;
        String instId = mixedPayRequest.getHeader().getInstId();
        String txnNum = mixedPayRequest.getHeader().getTxnNum();
        String bizType = mixedPayRequest.getHeader().getBizType();
        String acctType;
        String mchntFee;
        String scoreType;
        String totalAmt = "0.00";
        String feeType;

        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        if (mixedPayRequest.getPayInfoList() == null ||
                mixedPayRequest.getPayInfoList().isEmpty() ||
                mixedPayRequest.getPayInfoList().get(0).getPayAcctNo() == null) {
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        String payAcctNo = mixedPayRequest.getPayInfoList().get(0).getPayAcctNo();
        for (PayInfo payInfo : mixedPayRequest.getPayInfoList()) {
            totalAmt = AmountUtil.addition(totalAmt, payInfo.getTransAmt());
        }
        if (mixedPayRequest.getCouponInfo() != null && mixedPayRequest.getCouponInfo().getDiscountAmt() != null) {
            totalAmt = AmountUtil.addition(totalAmt, mixedPayRequest.getCouponInfo().getDiscountAmt());
        }
        if (AmountUtil.compare(mixedPayRequest.getOrderAmt(), totalAmt) != 0) {
            rglog.error("付款金额[{}]跟订单金额[{}]不一致", totalAmt, mixedPayRequest.getOrderAmt());
            throw new BizException(RespCodeEnum.TRANS_AMT_DISACCORD.getRespCode(), RespCodeEnum.TRANS_AMT_DISACCORD.getRespDesc());
        }

        /* 获取卡bin信息 */
        BinInfoService binInfoService = new BinInfoServiceImpl();
        BinInfo binInfo = binInfoService.getCardBinInfo(payAcctNo);
        if (binInfo == null) {
            rglog.error("根据卡号<{}>查询卡bin信息失败", payAcctNo);
            throw new BizException(RespCodeEnum.GET_CARD_BIN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_CARD_BIN_INFO_ERROR.getRespDesc());
        }

        /*检查订单可支付性*/
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoByUserOrderId(instId, mixedPayRequest.getUserOrderId());
        if (null == orderInfo) {
            rglog.error("订单信息不存在!");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        /*登记支付备注*/
        userOrderInfo.setOrderDesc(mixedPayRequest.getOrderDesc());
        /*获取商户订单*/
        List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();
        List<MchntOrderInfo> mchntOrderInfoListNew = new ArrayList<>();

        MchntService mchntService = new MchntServiceImpl();
        /*判断卡类型*/
        if (CardTypeEnum.DEBIT.getAcctType().equals(binInfo.getCardType())) {
            acctType = AcctTypeEnum.BANK_DEBIT.getAcctType();
            scoreType = OpmsParamConstant.SCORE_RATE_DR;
            feeType = FeeTypeEnum.BANK_DR_CARD.getFeeType();
        } else if (CardTypeEnum.CREDIT.getAcctType().equals(binInfo.getCardType()) ||
                CardTypeEnum.QCREDIT.getAcctType().equals(binInfo.getCardType())) {
            acctType = AcctTypeEnum.BANK_CREDIT.getAcctType();
            scoreType = OpmsParamConstant.SCORE_RATE_CR;
            feeType = FeeTypeEnum.BANK_CR_CARD.getFeeType();
        } else {
            rglog.error("不支持的卡类型<{}>", binInfo.getCardType());
            throw new BizException(RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespDesc());
        }
        xmlTreeUtil.setXmlTreeStringValue("FEE_TYPE", feeType);

        /*获取兑换比率*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam integralExchangeScale = sysParamService.getSysParamInfo(mixedPayRequest.getHeader().getInstId(), OpmsParamConstant.SCORE_RATE, scoreType);
        if (integralExchangeScale == null) {
            rglog.info("积分兑换规则未配置，instId:<{}>", mixedPayRequest.getHeader().getInstId());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }

        //判断是否只传入一笔积分支付
        List<PayInfo> payInfoList = mixedPayRequest.getPayInfoList().stream().filter(item -> "01".equals(item.getAcctType())).collect(Collectors.toList());
        if (payInfoList.size() != 1) {
            rglog.info("银行卡加积分支付的方式不支持多笔积分支付数据，scorePayListSize:<{}>", payInfoList.size());
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        //计算积分支付金额
        String scoreAmt = AmountUtil.multiplication(payInfoList.get(0).getTransScoreNum(), integralExchangeScale.getParamValue());
        if (AmountUtil.compare(payInfoList.get(0).getTransScoreCash(), scoreAmt) != 0) {
            rglog.error("积分金额[{}]跟抵扣金额[{}]不一致。积分兑换比例[{}]，积分数[{}]", scoreAmt, payInfoList.get(0).getTransScoreCash(), integralExchangeScale.getParamValue(), payInfoList.get(0).getTransScoreNum());
            throw new BizException(RespCodeEnum.TRANS_AMT_DISACCORD.getRespCode(), RespCodeEnum.TRANS_AMT_DISACCORD.getRespDesc());
        }

        //商户交易权限检查，限额检查，计算商户手续费
        List<TransLimitBean> transLimitBeanList = new ArrayList<>();
        CalcMchntFee clearMethod = new CalcMchntFee();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntOrderInfo.getMchntNo());
            if (null == mchntInfo) {
                rglog.error("查询商户基本信息失败<{}>", mchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            xmlTreeUtil.setXmlTreeStringValue("branchId", mchntInfo.getSignInstId());
            /*交易权限检查*/
            boolean checkResult = mchntService.checkMchntAuth(instId, mchntOrderInfo.getMchntNo(), null, txnNum, bizType, acctType);
            if (!checkResult) {
                rglog.error("商户<{}>无此交易权限!", mchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
            }
            /*限额检查*/
            int limitFlag = mchntService.checkMchntTransLimit(instId, mchntOrderInfo.getRealSettleAmt(), LimitAcctTypeEnum.ALL, mchntOrderInfo.getMchntNo(), null, txnNum);
            if (limitFlag == 2 || limitFlag == 3) {
                rglog.error("商户金额超限");
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            } else if (limitFlag == 1) {
                /*不支持信用卡*/
                xmlTreeUtil.setXmlTreeStringValue("disablePayChannels", "pcredit");
            }

            /*计算商户手续费*/
            CalcMchntFeeBean clearSrcObj = new CalcMchntFeeBean();
            clearSrcObj.setMchntNo(mchntOrderInfo.getMchntNo());
            clearSrcObj.setTransAmt(mchntOrderInfo.getOrderAmt());
            clearSrcObj.setInstId(instId);
            clearSrcObj.setStageCode("");
            clearSrcObj.setStageNum("");
            clearSrcObj.setSubProdType(feeType);
            clearSrcObj.setIgasBizProdType(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            CalcMchntFeeResultBean calcMchntFeeResultBean = clearMethod.calcPayFee(clearSrcObj);
            if (calcMchntFeeResultBean == null) {
                rglog.error("计算商户手续费失败");
                throw new BizException(RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespCode(), RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespDesc());
            }

            mchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
            mchntFee = calcMchntFeeResultBean.getMchntFee();
            //特殊费率商户设置费率标示
            if (CalcFlagEnum.CALCFLAG_SPEFEENOTCALC.getCalcFlag().equals(calcMchntFeeResultBean.getCalcFlag())) {
                mchntOrderInfo.setFeeInputMode("0");
            } else {
                mchntOrderInfo.setFeeInputMode(calcMchntFeeResultBean.getFeeInputMode());
            }
            mchntOrderInfo.setFeeRate(calcMchntFeeResultBean.getFeeRate());
            mchntOrderInfo.setFeeCappingAmt(calcMchntFeeResultBean.getFeeCappingAmt());
            mchntOrderInfo.setFeeFixedAmt(calcMchntFeeResultBean.getFeeFixedAmt());
            mchntOrderInfo.setMchntFee(mchntFee);
            mchntOrderInfo.setSysSeqNum(sysSeqNum);
            mchntOrderInfo.setTxnDate(userOrderInfo.getTxnDate());
            mchntOrderInfo.setTxnTime(userOrderInfo.getTxnTime());
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            mchntOrderInfo.setMchntDiscountFee("0.00");
            mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntFee));
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            /*判断是否独立维护资料的门店*/
            if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
            }
            mchntOrderInfoListNew.add(mchntOrderInfo);
        }
        //交易限额信息存入缓存
        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.TRANS_LIMIT_INFO_LIST, transLimitBeanList);

        /*更新订单明细表*/
        List<MchntOrderDetail> mchntOrderDetailList = new ArrayList<>();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoListNew) {
            MchntOrderDetailMapper mchntOrderDetailMapper = new MchntOrderDetailMapperImpl();
            List<MchntOrderDetail> oneMchntOrderDetailList = mchntOrderDetailMapper.selectMchntOrderDetailByMchntOrderId(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo(), mchntOrderInfo.getMchntOrderId());
            if (!CollectionUtils.isEmpty(oneMchntOrderDetailList)) {
                for (MchntOrderDetail mchntOrderDetail : oneMchntOrderDetailList) {
                    mchntOrderDetail.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
                }
                mchntOrderDetailList.addAll(oneMchntOrderDetailList);
            }
        }
        if (!CollectionUtils.isEmpty(mchntOrderDetailList)) {
            orderService.updateOrderInfo(null, null, mchntOrderDetailList, null);
        }
        /*更新用户订单，商户订单*/
        if (!updateOrderInfo(userOrderInfo, mchntOrderInfoListNew, null)) {
            rglog.error("更新订单信息失败");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(),
                    RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
        }

        /*判断借贷记调用不同接口处理*/
        if (CardTypeEnum.DEBIT.getAcctType().equals(binInfo.getCardType())) {
            return debitCardPay(scoreAmt, mixedPayRequest, userOrderInfo, mchntOrderInfoListNew);
        } else if (CardTypeEnum.CREDIT.getAcctType().equals(binInfo.getCardType()) ||
                CardTypeEnum.QCREDIT.getAcctType().equals(binInfo.getCardType())) {
            return creditCardPay(scoreAmt, mixedPayRequest, userOrderInfo, mchntOrderInfoListNew);
        } else {
            rglog.error("不支持的卡类型<{}>", binInfo.getCardType());
            throw new BizException(RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_ACCTTYPE_ERROR.getRespDesc());
        }
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        MobileBankScanPayResponse mobileBankScanPayResponse = (MobileBankScanPayResponse) bizResponse.getResult();
        ConvertUtil.convertInput(mobileBankScanPayResponse);
    }

    /**
     * 信用卡快捷支付
     *
     * @param scoreAmt           积分兑换金额
     * @param mixedPayRequest    支付请求
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @return 响应
     * @throws Exception 异常
     */
    private BizResponse creditCardPay(String scoreAmt, MixedPayRequest mixedPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        List<ChannelCallCfg> esbChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ESB.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        List<PayInfo> payInfoList = mixedPayRequest.getPayInfoList().stream().filter(item -> "00".equals(item.getAcctType())).collect(Collectors.toList());
        OrderService orderService = new OrderServiceImpl();
        DubboService dubboService = new DubboServiceImpl();
        String discountFlag = "N";
        int iReturnCode = 0;

        BizResponse<MobileBankScanPayResponse> bizResponse = new BizResponse();
        MobileBankScanPayResponse mobileBankScanPayResponse = new MobileBankScanPayResponse();
        mobileBankScanPayResponse.setHeader(mixedPayRequest.getHeader());

        //用户实际支付金额
        String realPayAmt = AmountUtil.subtraction(userOrderInfo.getOrderAmt(), scoreAmt);

        /*调用银数密码校验接口*/

        /*登记营销支付订单表*/
        PayOrderInfo mompPayOrderInfo = registerPayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_CREDIT.getAcctType(), mompChannelCallCfgList.get(0), "0.00");
        if (mompPayOrderInfo == null) {
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        //调用营销计算
        mompPayOrderInfo.setRealPayAmt(mixedPayRequest.getOrderAmt());
        mompCount(mixedPayRequest, mompChannelCallCfgList.get(0), scoreAmt, userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);

        /*登记积分支付订单表*/
        PayOrderInfo scorePayOrderInfo = registerScorePayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_CREDIT.getAcctType(), esbChannelCallCfgList.get(0));
        if (scorePayOrderInfo == null) {
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null, orderService);
            mompRevsal(discountFlag);
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        /*调用积分支付接口*/
        scorePay(discountFlag, mixedPayRequest, userOrderInfo, mchntOrderInfoList, scorePayOrderInfo, esbChannelCallCfgList.get(0));

        /*登记esb支付订单表*/
        PayOrderInfo esbPayOrderInfo = convPayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_CREDIT.getAcctType(), esbChannelCallCfgList.get(1));
        esbPayOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
        esbPayOrderInfo.setRealPayAmt(realPayAmt);
        esbPayOrderInfo.setPayerAcctInfo(payInfoList.get(0).getAcctType());
        esbPayOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mixedPayRequest.getHeader().getInstId()));
        if (!orderService.registerOrderInfo(null, null, esbPayOrderInfo)) {
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null, orderService);
            mompRevsal(discountFlag);
            ConvertUtil.convertInput(mixedPayRequest);
            throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
        }

        /* 调用esb银数消费接口 */
        //TODO step1.调用本行快捷支付  -贷记卡  分析调用结果，由项目组实现该部分交易
        // （1）通讯级失败或业务失败，调用营销冲正 mompRevsal，更新订单为失败，updateOrderFail，抛出调用业务异常
        // （2）业务超时，更新支付订单为处理中，抛出调用异常为处理中
        // （3）业务成功，更新订单状态，程序继续执行

        /*更新商户累计限额*/
        MchntService mchntService = new MchntServiceImpl();
        mchntService.updateMchntTransLimit(mchntOrderInfoList);

        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);

        /*非d0支付后异步调用虚拟记账接口*/
        virtAcctMultiMchntAdjust(mixedPayRequest, userOrderInfo, mchntOrderInfoList);


        if (userOrderInfo.getNotifyBackUrl() != null && !userOrderInfo.getNotifyBackUrl().isEmpty()) {
            /*异步通知给商户后台系统*/
            //todo
        }

        //响应信息
        mobileBankScanPayResponse.setDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), realPayAmt));
        mobileBankScanPayResponse.setActualAmt(realPayAmt);
        bizResponse.setResult(mobileBankScanPayResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }


    /**
     * 营销优惠试算
     *
     * @param mixedPayRequest    合并支付请求
     * @param channelCallCfg     交易映射关系
     * @param scoreAmt           积分兑换金额
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @throws Exception 异常
     */
    private void mompCount(MixedPayRequest mixedPayRequest, ChannelCallCfg channelCallCfg, String scoreAmt,
                           UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo) throws Exception {

        /*获取营销产品编码*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(userOrderInfo.getInstId(), OpmsParamConstant.MOMP_PROD_CODE,
                mixedPayRequest.getHeader().getTxnNum() + mixedPayRequest.getHeader().getBizType());
        if (sysParam == null) {
            rglog.warn("收银台营销产品代码未配置，交易终止。instId:<{}>", mixedPayRequest.getHeader().getInstId());
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        DubboService dubboService = new DubboServiceImpl();
        OrderService orderService = new OrderServiceImpl();
        String discountFlag = AppParamConstant.NO;
        String feeDiscountFlag = AppParamConstant.NO;

        //营销优惠金额试算
        Header header = new Header();
        header.setInstId(mixedPayRequest.getHeader().getInstId());
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setBizType(OpmsParamConstant.DUBBO_DEFAULT_BIZ_TYPE);
        header.setTxnNum(channelCallCfg.getCallChannelTxn());
        header.setVersion("1.0.0");
        header.setTraceNo(sysSeqNum + channelCallCfg.getCallIndex());
        header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
        comboPaymentRequest.setHeader(header);
        comboPaymentRequest.setUserId(userOrderInfo.getUserId());
        comboPaymentRequest.setBizProdCode(sysParam.getParamValue());
        comboPaymentRequest.setMchntOrderId(userOrderInfo.getMchntOrderId());
        comboPaymentRequest.setTransAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), scoreAmt));
        List<PaymentOrderDetailBean> orderDetailList = new ArrayList<>();
        convertOrderDetail(orderDetailList, mchntOrderInfoList);
        comboPaymentRequest.setOrderDetailList(orderDetailList);
        List<PaymentOrderCouponInfoBean> couponInfoList = new ArrayList<>();
        if (mixedPayRequest.getCouponInfo() != null && mixedPayRequest.getCouponInfo().getDiscountId() != null) {
            discountFlag = "Y";
            PaymentOrderCouponInfoBean paymentOrderCouponInfoBean = new PaymentOrderCouponInfoBean();
            paymentOrderCouponInfoBean.setCouponNo(mixedPayRequest.getCouponInfo().getDiscountId());
        }
        comboPaymentRequest.setCouponInfoList(couponInfoList);
        xmlTreeUtil.setXmlTreeObjectValue("comboPaymentRequest", comboPaymentRequest);
        Result<ComboPaymentResponse> responseResult = (Result<ComboPaymentResponse>) dubboService.callDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, "comboPayment", comboPaymentRequest);

        //试算结果分析
        if (null == responseResult || !responseResult.isSuccess()) {
            rglog.error("调用dubbo服务comboPayment失败");
            if (AppParamConstant.YES.equals(discountFlag)) {
                /*更新订单表状态*/
                updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            }
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }
        } else {

            ComboPaymentResponse comboPaymentResponse = responseResult.getResult();
            if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.YES.equals(discountFlag)) {

                /*业务响应失败*/
                rglog.error("调用服务失败，返回码respCode=[]，respDesc=[{}]", comboPaymentResponse.getRespCode(), comboPaymentResponse.getRespDesc());
                updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(comboPaymentResponse.getRespCode()) && AppParamConstant.NO.equals(discountFlag)) {

                /*更新支付订单表状态失败，由于未使用优惠券，可继续往下支付*/
                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(null, null, payOrderInfo)) {
                    rglog.error("更新订单表状态失败");
                }
            } else {

                //判断是否使用营销 参与营销，不实时入账
                if (AmountUtil.compare(comboPaymentResponse.getTransAmt(), comboPaymentResponse.getTxnAmt()) != 0) {
                    discountFlag = AppParamConstant.YES;
                }

                String realPayAmt = comboPaymentResponse.getTxnAmt();
                //用户订单表数据更新
                if (mixedPayRequest.getCouponInfo() != null && mixedPayRequest.getCouponInfo().getDiscountId() != null) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(mixedPayRequest.getCouponInfo().getDiscountId(), mixedPayRequest.getCouponInfo().getDiscountAmt());
                    userOrderInfo.setDiscountInfo(jsonObject.toJSONString());
                }
                userOrderInfo.setRealDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), realPayAmt));
                userOrderInfo.setRealPayAmt(realPayAmt);

                List<PaymentOrderDetailBean> orderDetailBeanList = comboPaymentResponse.getOrderDetailList();
                if (orderDetailBeanList == null || orderDetailBeanList.isEmpty()) {
                    rglog.warn("营销返回数据有误，订单明细列表未返回。orderDetailBeanListSize:<{}>", orderDetailBeanList.size());
                    updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                    xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                    mompRevsal(null);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }

                //计算商户的优惠信息
                /*通道优惠金额累加*/
                String channelDiscountAmt = "0.00";
                for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {

                    List<PaymentOrderDetailBean> paymentOrderDetailBeanList = orderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfo.getMchntNo())).collect(Collectors.toList());
                    if (paymentOrderDetailBeanList.isEmpty()) {
                        rglog.warn("当前商户无营销优惠信息，在订单明细列表中无当前商户数据。mchntNo:<{}>", mchntOrderInfo.getMchntNo());
                        updateOrderFail(userOrderInfo, mchntOrderInfoList, payOrderInfo, orderService);
                        xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                        mompRevsal(null);
                        throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                    }


                    /*
                     * 判断是否是免充值的商户优惠类型
                     * 若不是则使用营销返回的数据
                     * 商户清算本金金额=原商户清算本金金额
                     * 商户结算金额=商户清算本金金额-实收商户手续费
                     * 若是则需要重新获取商户清算本金金额并重新计算商户手续费
                     * 商户清算本金金额=原商户清算本金金额-免充值金额
                     * 商户结算金额=商户清算本金金额-商户应收手续费(调用批量结算结果)+手续费优惠金额(营销返回)
                     */
                    String noRechargeAmt = "0.00";
                    if ("0".equals(paymentOrderDetailBeanList.get(0).getMoneyOffSettlementMethod())) {
                        /*免充值需要减去商户满减补贴金额*/
                        noRechargeAmt = AmountUtil.addition(noRechargeAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyMchnt());
                    } else {
                        channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal());
                    }
                    if ("0".equals(paymentOrderDetailBeanList.get(0).getCouponMchntSettleMethod())) {
                        /*免充值需要减去商户卡券补贴金额*/
                        noRechargeAmt = AmountUtil.addition(noRechargeAmt, paymentOrderDetailBeanList.get(0).getCouponMchntSubsidy());
                    } else {
                        channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy());
                    }
                    rglog.debug("商户免充值金额:<{}>", noRechargeAmt);
                    //对客营销金额=商户免充值营销金额
                    mchntOrderInfo.setCustomerMarketAmt(noRechargeAmt);
                    //商户实际清算本金=原商户实际清算本金-对客营销金额
                    mchntOrderInfo.setRealSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), noRechargeAmt));

                    //商户手续费优惠金额
                    String mchntFeeDiscount = mchntOrderInfo.getMchntDiscountFee();
                    if (paymentOrderDetailBeanList.get(0).getMchntFeeDiscount() != null && AmountUtil.compare(paymentOrderDetailBeanList.get(0).getMchntFeeDiscount(), "0") == 1) {
                        mchntFeeDiscount = paymentOrderDetailBeanList.get(0).getMchntFeeDiscount();
                        feeDiscountFlag = AppParamConstant.YES;
                    }

                    //用户享受营销之后商户就不实时清算
                    if (AppParamConstant.YES.equals(discountFlag)) {
                        rglog.info("当前用户享受营销,商户不支持实时清算");
                        mchntOrderInfo.setRealSettleFlag(OpmsParamConstant.OPMS_PARAM_NO);
                    }

                    //根据免充值金额对商户清算本金金额、商户结算金额、商户实收手续费、商户优惠手续费进行赋值
                    if (AmountUtil.compare(noRechargeAmt, "0.00") == 1) {

                        rglog.debug("商户免充值金额大于0,需要重新计算商户手续费....");
                        //更新商户订单数据
                        mchntOrderInfo.setMchntFee(paymentOrderDetailBeanList.get(0).getMchntFeeReceivable());
                        mchntOrderInfo.setRealMchntFee(paymentOrderDetailBeanList.get(0).getMchntFeeActual());
                        mchntOrderInfo.setMchntDiscountFee(paymentOrderDetailBeanList.get(0).getMchntFeeDiscount());
                        mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getRealMchntFee()));
                        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    } else {

                        rglog.debug("商户免充值金额小于等于0,使用营销调用结果计算商户手续费信息....");
                        /*实收商户手续费金额*/
                        String mchntFeeActual = mchntOrderInfo.getRealMchntFee();
                        if (paymentOrderDetailBeanList.get(0).getMchntFeeActual() != null) {
                            mchntFeeActual = paymentOrderDetailBeanList.get(0).getMchntFeeActual();
                        }

                        /*实时清算时，实收手续费四舍五入处理*/
                        if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                            mchntFeeActual = AmountUtil.rounding(mchntFeeActual, 2);
                            if (mchntFeeDiscount == null || AmountUtil.compare(mchntFeeDiscount, "0") == 0) {
                                mchntFeeDiscount = "0.00";
                            } else {
                                mchntFeeDiscount = AmountUtil.subtraction(mchntOrderInfo.getMchntFee(), mchntFeeActual);
                            }
                        }
                        mchntOrderInfo.setMchntDiscountFee(mchntFeeDiscount);
                        mchntOrderInfo.setRealMchntFee(mchntFeeActual);
                        mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntFeeActual));
                        if (paymentOrderDetailBeanList.get(0).getCouponNo() != null) {
                            mchntOrderInfo.setRedeemCouponIds(paymentOrderDetailBeanList.get(0).getCouponNo());
                        }
                        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    }
                }

                /*营销系统返回成功，更新订单支付订单状态为成功*/
                payOrderInfo.setRealPayAmt(AmountUtil.subtraction(comboPaymentResponse.getTransAmt(), comboPaymentResponse.getTxnAmt()));
                payOrderInfo.setChannelDiscountAmt(comboPaymentResponse.getTotalSubsidy());
                payOrderInfo.setSettleDate(DateUtil.getCurrentDate());
                payOrderInfo.setRespCode(responseResult.getResult().getRespCode());
                payOrderInfo.setRespDesc(responseResult.getResult().getRespDesc());
                payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                    rglog.warn("更新营销支付订单表失败");
                }
            }

            //是否使用优惠标识存入节点内
            if (AppParamConstant.NO.equals(discountFlag) && AppParamConstant.NO.equals(feeDiscountFlag)) {
                xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);
            } else {
                xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
            }
        }
    }


    /**
     * 更新订单结果为失败
     *
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @param orderService       订单组件
     */
    private void updateOrderFail(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo, OrderService orderService) throws Exception {

        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
        userOrderInfo.setUpdateTime(currentDateTime);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            mchntOrderInfo.setUpdateTime(currentDateTime);
        }

        if (null == payOrderInfo) {
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
                rglog.error("更新订单表状态失败");
            }
        } else {
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            payOrderInfo.setUpdateTime(currentDateTime);
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }
        }
    }

    /**
     * 借记卡支付
     *
     * @param scoreAmt           积分兑换金额
     * @param mixedPayRequest    合并支付请求
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @return
     * @throws Exception 异常
     */
    private BizResponse debitCardPay(String scoreAmt, MixedPayRequest mixedPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<ChannelCallCfg> esbChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ESB.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
        DubboService dubboService = new DubboServiceImpl();
        OrderService orderService = new OrderServiceImpl();
        String discountFlag = "N";
        int iReturnCode = 0;

        /*获取渠道户*/
        CsmcService csmcService = new CsmcServiceImpl();
        String roleActualAcctNo = csmcService.getRoleActualAcctNo(mixedPayRequest.getHeader().getInstId(), SettleAcctTypeEnum.BANK_PAYCHNL_SUBJECT.getSettleAcct(), null);
        if (StringUtil.isEmptyOrNull(roleActualAcctNo)) {
            rglog.error("获取内部户失败，instId<{}>,acctType<{}>,ruleType", mixedPayRequest.getHeader().getInstId(), SettleAcctTypeEnum.BANK_PAYCHNL_SUBJECT.getSettleAcct());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null, orderService);
            mompRevsal(discountFlag);
            ConvertUtil.convertInput(mixedPayRequest);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        BizResponse<MobileBankScanPayResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        MobileBankScanPayResponse mobileBankScanPayResponse = new MobileBankScanPayResponse();
        mobileBankScanPayResponse.setHeader(mixedPayRequest.getHeader());
        List<PayInfo> payInfoList = mixedPayRequest.getPayInfoList().stream().filter(item -> "00".equals(item.getAcctType())).collect(Collectors.toList());

        //积分兑换金额计算
        String realPayAmt = AmountUtil.subtraction(userOrderInfo.getOrderAmt(), scoreAmt);

        /*调用核心密码校验接口*/

        /*登记支付订单表*/
        PayOrderInfo mompPayOrderInfo = registerPayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_DEBIT.getAcctType(), mompChannelCallCfgList.get(0), "0.00");
        if (mompPayOrderInfo == null) {
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }
        //调用营销计算
        mompPayOrderInfo.setRealPayAmt(mixedPayRequest.getOrderAmt());
        mompCount(mixedPayRequest, mompChannelCallCfgList.get(0), scoreAmt, userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);

        /*登记积分支付订单表*/
        PayOrderInfo scorePayOrderInfo = registerScorePayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_DEBIT.getAcctType(), esbChannelCallCfgList.get(1));
        if (scorePayOrderInfo == null) {
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null, orderService);
            mompRevsal(discountFlag);
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        /*调用积分支付接口*/
        scorePay(discountFlag, mixedPayRequest, userOrderInfo, mchntOrderInfoList, scorePayOrderInfo, esbChannelCallCfgList.get(1));

        /*登记esb支付订单表*/
        PayOrderInfo esbPayOrderInfo = convPayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_DEBIT.getAcctType(), esbChannelCallCfgList.get(2));
        esbPayOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
        esbPayOrderInfo.setRealPayAmt(realPayAmt);
        esbPayOrderInfo.setPayerAcctInfo(payInfoList.get(0).getPayAcctNo());
        esbPayOrderInfo.setPayeeAcctInfo(roleActualAcctNo);
        esbPayOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mixedPayRequest.getHeader().getInstId()));
        if (!orderService.registerOrderInfo(null, null, esbPayOrderInfo)) {
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null, orderService);
            mompRevsal(discountFlag);
            ConvertUtil.convertInput(mixedPayRequest);
            throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
        }


        /* 调用esb核心消费接口 */
        //TODO step2.调用核心借记卡快捷支付  分析调用结果，由项目组实现该部分交易
        // （1）通讯级失败或业务失败（非超时/成功），调用营销冲正 mompRevsal，更新订单为失败，updateOrderFail，抛出调用业务异常
        // （2）业务超时，更新支付订单为处理中，抛出调用异常为处理中
        // （3）业务成功，更新订单状态，程序继续执行

        /*更新商户累计限额*/
        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);
        MchntService mchntService = new MchntServiceImpl();
        mchntService.updateMchntTransLimit(mchntOrderInfoList);

        /*判断是否实时入账*/
        if (AppParamConstant.YES.equals(mchntOrderInfoList.get(0).getRealSettleFlag())) {
            /*调用esb记账*/
            if (!esbChannelCallCfgList.isEmpty()) {
                mchntRealTimeAccouting(mchntOrderInfoList, esbChannelCallCfgList.get(0), esbPayOrderInfo.getPayType());
                iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
                if (0 != iReturnCode) {
                    rglog.error("提交交易结果异步通知给商户失败!");
                }
            } else {
                rglog.error("未配置d0交易映射，不实时入账");
            }
            /*d0清算后调用微信消息推送*/
            rglog.error("订单全为特殊计费，不记商户虚拟账，直接推送通知");
            iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
            if (0 != iReturnCode) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
        } else {
            /*非d0支付后异步调用虚拟记账接口*/
            virtAcctMultiMchntAdjust(mixedPayRequest, userOrderInfo, mchntOrderInfoList);
        }


        mobileBankScanPayResponse.setDiscountAmt(userOrderInfo.getRealDiscountAmt());
        mobileBankScanPayResponse.setActualAmt(userOrderInfo.getRealPayAmt());
        bizResponse.setResult(mobileBankScanPayResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    private PayOrderInfo registerPayOrderInfo(UserOrderInfo userOrderInfo, MixedPayRequest request, String acctType, ChannelCallCfg channelCallCfg, String realTransAmt) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setOrderCcy(request.getOrderCcy());
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setPayType(PayTypeEnum.OTHER.getPayType());
        payOrderInfo.setPayerAcctType(acctType);
        payOrderInfo.setRealPayAmt(realTransAmt);
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }
        return payOrderInfo;
    }

    private PayOrderInfo registerScorePayOrderInfo(UserOrderInfo userOrderInfo, MixedPayRequest request, String acctType, ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<PayInfo> payInfoList = request.getPayInfoList().stream().filter(item -> "01".equals(item.getAcctType())).collect(Collectors.toList());
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setOrderCcy(request.getOrderCcy());
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setOrderAmt(payInfoList.get(0).getTransScoreNum());
        payOrderInfo.setRealPayAmt(payInfoList.get(0).getTransScoreCash());
        payOrderInfo.setPayType(PayTypeEnum.SCORE.getPayType());
        payOrderInfo.setPayerAcctType(acctType);
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }
        return payOrderInfo;
    }

    private PayOrderInfo convPayOrderInfo(UserOrderInfo userOrderInfo, MixedPayRequest request, String acctType, ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setOrderCcy(request.getOrderCcy());
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
        payOrderInfo.setPayerAcctType(acctType);
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

        return payOrderInfo;
    }


    int updatePayOrderInfo(PayOrderInfo payOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppParamConstant.DATABASE_CONF_NODE, AppParamConstant.OLTP_POOL_NAME);
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);

        dbsUtil.dbsBeginTransaction();
        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        int recode = payOrderInfoMapper.updatePayOrderInfoByPrimaryKey(payOrderInfo);
        if (recode != 0) {
            dbsUtil.dbsEndTransaction(false);
            return recode;
        }
        dbsUtil.dbsEndTransaction(true);
        return recode;
    }

    /**
     * 营销计算
     *
     * @param orderDetailList    营销订单
     * @param mchntOrderInfoList 商户订单
     */
    private void convertOrderDetail(List<PaymentOrderDetailBean> orderDetailList, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            PaymentOrderDetailBean paymentOrderDetailBean = new PaymentOrderDetailBean();
            paymentOrderDetailBean.setMchntNo(mchntOrderInfo.getMchntNo());
            if (mchntOrderInfo.getOrderDiscountAmt() != null && !mchntOrderInfo.getOrderDiscountAmt().isEmpty()) {
                paymentOrderDetailBean.setOrderAmt(AmountUtil.subtraction(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getOrderDiscountAmt()));
            } else {
                paymentOrderDetailBean.setOrderAmt(mchntOrderInfo.getOrderAmt());
            }
            paymentOrderDetailBean.setMchntFeeReceivableRate(mchntOrderInfo.getFeeRate());
            paymentOrderDetailBean.setMchntSettleAmt(mchntOrderInfo.getRealSettleAmt());
            paymentOrderDetailBean.setMchntFeeReceivable(mchntOrderInfo.getMchntFee());
            paymentOrderDetailBean.setFeeInputMode(mchntOrderInfo.getFeeInputMode());
            paymentOrderDetailBean.setFeeType(xmlTreeUtil.getXmlTreeStringValue("FEE_TYPE"));
            paymentOrderDetailBean.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            orderDetailList.add(paymentOrderDetailBean);
        }
    }

    /*商户虚拟账户记账*/
    void virtAcctMultiMchntAdjust(MixedPayRequest mixedPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        //虚拟账户记账或预授权完成，购买卡券交易和担保支付交易不记虚拟账户
        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "01".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            rglog.info("购买卡券交易或担保支付的交易,bizSceneType:<{}>，不记商户虚拟账,但推送消息", mchntOrderInfoList.get(0).getBizSceneType());
            if (0 != asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0)) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
            return;
        }

        //手续费特殊计费的交易不调用虚拟账户记账
        if ("0".equals(mchntOrderInfoList.get(0).getFeeInputMode())) {
            rglog.info("订单全为特殊计费，不记商户虚拟账，直接推送通知");
            int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
            if (0 != iReturnCode) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
            return;
        }

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = null;
        DubboService dubboService = new DubboServiceImpl();
        List<ChannelCallCfg> ChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ACCT.getChannelType())).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = ChannelCallCfgList.get(0);
        String realPayAmt = "0.00";
        //商户收支两线的标识
        char incomeFlag = '1';

        try {
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
            VirtAcctMultiMchntAdjustRequest request = new VirtAcctMultiMchntAdjustRequest();
            cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
            BeanUtil.beanCopy(mixedPayRequest.getHeader(), header);
            header.setTxnNum(channelCallCfg.getCallChannelTxn());
            header.setTraceNo(sysSeqNum + channelCallCfg.getCallIndex());
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
            request.setHeader(header);
            request.setAcctType("00");
            request.setDebitCreditFlag("C");
            List<MchtAdjustDetail> mchtAdjustDetailList = new ArrayList<>();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                if ("0".equals(mchntOrderInfo.getFeeInputMode())) {
                    continue;
                }
                MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
                mchtAdjustDetail.setUserType("00");
                mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                    mchtAdjustDetail.setUserId(mchntInfo.getChainMchntNo());
                } else {
                    mchtAdjustDetail.setUserId(mchntInfo.getMchntNo());
                }
                /*收支两线的商户使用商户清算本金金额到虚拟账户记账，合并轧差的商户使用商户结算净额到虚拟账户记账*/
                rglog.info("当前商户:<{}>的结算模式:<{}>", mchntInfo.getMchntNo(), mchntInfo.getMchntSettleMode());
                if (incomeFlag == mchntInfo.getMchntSettleMode().charAt(1)) {
                    realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getRealSettleAmt());
                    mchtAdjustDetail.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                } else {
                    realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getMchntSettleAmt());
                    mchtAdjustDetail.setTransAmt(mchntOrderInfo.getMchntSettleAmt());
                }
                //如果商户记虚拟账户的金额等于0则不记该商户的虚拟账户
                if (AmountUtil.compare("0", mchtAdjustDetail.getTransAmt()) == 0) {
                    continue;
                }
                mchtAdjustDetailList.add(mchtAdjustDetail);
            }

            if (mchtAdjustDetailList.isEmpty()) {
                /*特殊计费订单不记虚拟账，调用微信消息推送*/
                rglog.error("订单全为特殊计费，不记商户虚拟账，直接推送通知");
                int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
                if (0 != iReturnCode) {
                    rglog.error("提交交易结果异步通知给商户失败!");
                }
                return;
            }
            List<MchtAdjustDetail> mchtAdjustDetailListFinal = new ArrayList<>();
            /*按商户分组去重，累计求和*/
            Map<String, List<MchtAdjustDetail>> groupByUserId = mchtAdjustDetailList.stream().collect(Collectors.groupingBy(MchtAdjustDetail::getUserId));
            for (Map.Entry<String, List<MchtAdjustDetail>> entryUserId : groupByUserId.entrySet()) {
                String totalTransAmt = "0";
                String userId = entryUserId.getKey();
                List<MchtAdjustDetail> entryMchtAdjustDetailList = entryUserId.getValue();
                for (MchtAdjustDetail mchtAdjustDetail : entryMchtAdjustDetailList) {
                    totalTransAmt = AmountUtil.addition(totalTransAmt, mchtAdjustDetail.getTransAmt());
                }
                MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
                mchtAdjustDetail.setUserType("00");
                mchtAdjustDetail.setUserId(userId);
                mchtAdjustDetail.setTransAmt(totalTransAmt);
                mchtAdjustDetailListFinal.add(mchtAdjustDetail);
            }
            request.setMchtAdjustDetailList(mchtAdjustDetailListFinal);

            /*记账前登记支付订单表*/
            PayOrderInfo acctPayOrderInfo = registerPayOrderInfo(userOrderInfo, mixedPayRequest, AcctTypeEnum.BANK_ACCT.getAcctType(), channelCallCfg, realPayAmt);
            if (acctPayOrderInfo == null) {
                rglog.error("登记虚拟账户记账支付订单失败");
                return;
            }

            //异步调起虚拟账户记账服务
            int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_ACCT_VIRTACCT_SERVICE,
                    OpmsParamConstant.DUBBO_ACCT_VIRTACCTMULTIMCHNTADJUST, request, OpmsServiceConstant.ASYN_VIRTACCT_MULTIMCHNT_ADJUST_SERVICE);
            if (iReturnCode != 0) {
                rglog.error("异步虚拟账户记账服务注册失败！");
            } else {
                rglog.error("异步虚拟账户记账服务注册成功！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("登记虚拟账户记账支付订单失败:<{}>", e);
            return;
        }

    }

    /*商户实时入账*/
    private void mchntRealTimeAccouting(List<MchntOrderInfo> mchntOrderInfoList, ChannelCallCfg channelCallCfg, String payType) throws Exception {
        DubboService dubboService = new DubboServiceImpl();
        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType()) || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            rglog.error("购买卡券交易，不实时入账");
            return;
        }
        int callIndex = Integer.parseInt(channelCallCfg.getCallIndex());
        int iReturnCode;
        String settleAcctType;
        String channelBizType = ShareParamConstant.SUB_SYS_ID_D0_REALTIME;
        if (PayTypeEnum.BANK_CARD.getPayType().equals(payType)) {
            settleAcctType = SettleAcctTypeEnum.BANK_PAYCHNL_SUBJECT.getSettleAcct();
        } else {
            settleAcctType = SettleAcctTypeEnum.DZ_SUBJECT.getSettleAcct();
            channelBizType = ShareParamConstant.SUB_SYS_ID_D0_REALTIME;
        }
        /*获取渠道户*/
        CsmcService csmcService = new CsmcServiceImpl();
        String roleActualAcctNo = csmcService.getRoleActualAcctNo(mchntOrderInfoList.get(0).getInstId(), settleAcctType, null);
        if (StringUtil.isEmptyOrNull(roleActualAcctNo)) {
            rglog.error("获取付款账户异常，d0失败转t1处理");
            return;
        }
        //商户收支两线的标识
        char incomeFlag = '1';
        MchntService mchntService = new MchntServiceImpl();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            /*查询商户结算账户信息表，判断结算周期及结算账户类型*/
            MchntInfo mchntInfo;
            try {
                mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                List<MchntAcctInfo> mchntAcctInfoList;
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                    mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntInfo.getChainMchntNo());
                } else {
                    mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                }
                Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getBaseProdCode().equals(mchntOrderInfo.getBizProdCode()) && item.getFundType().equals("00")).findFirst();
                if (!mchntAcctInfoOpt.isPresent()) {
                    rglog.error("获取商户结算账户信息失败，商户实时入账失败，转t1");
                    continue;
                }

                //收支两线商户取商户清算本金
                String mchntAmt;
                if (incomeFlag == mchntInfo.getMchntSettleMode().charAt(1)) {
                    mchntAmt = mchntOrderInfo.getRealSettleAmt();
                } else {
                    mchntAmt = mchntOrderInfo.getMchntSettleAmt();
                }

                //登记实时入账支付订单表
                PayOrderInfo payOrderInfo = registerD0PayOrderInfo(mchntOrderInfo, roleActualAcctNo, AcctTypeEnum.BANK_ACCT.getAcctType(),
                        mchntAcctInfoOpt.get().getSettleAcctNo(), mchntAcctInfoOpt.get().getSettleAcctType(), channelCallCfg, String.valueOf(callIndex), mchntAmt);
                if (payOrderInfo == null) {
                    continue;
                }

                //实时入账
                //TODO 由项目组实现该部分 调用D0实时清算，后调用AsynMchntD0AccoutingService根据清算结果进行处理
                iReturnCode = dubboService.asynCallDubboService("dubboService", "method", "request", "AsynMchntD0AccoutingService");
                if (iReturnCode != 0) {
                    rglog.error("异步d0入账服务注册失败！");
                }
                callIndex++;
            } catch (Exception e) {
                rglog.error(e.getMessage());
            }
        }
    }

    /*登记D0记账支付订单流水*/
    private PayOrderInfo registerD0PayOrderInfo(MchntOrderInfo mchntOrderInfo, String payAcctNo, String payAcctType, String payeeAcctNo, String payeeAcctType, ChannelCallCfg channelCallCfg, String callIndex, String mchntAmt) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(mchntOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(OpmsParamConstant.D0_ACCOUTING_TXN_NUM);
        try {
            payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
            if (callIndex != null) {
                payOrderInfo.setDstCallIndex(callIndex);
                payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + callIndex);
                payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + callIndex);
            } else {
                payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
                payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
                payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
            }

            payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
            payOrderInfo.setRealPayAmt(mchntAmt);
            payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
            payOrderInfo.setPayerAcctType(payAcctType);
            payOrderInfo.setPayerAcctInfo(payAcctNo);
            payOrderInfo.setPayeeAcctType(payeeAcctType);
            payOrderInfo.setPayeeAcctInfo(payeeAcctNo);
            payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
                rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
                return null;
            }
            return payOrderInfo;
        } catch (Exception e) {
            rglog.error(e.getMessage());
            return null;
        }
    }

    /**
     * 积分支付
     *
     * @param discountFlag       营销
     * @param mixedPayRequest    合并支付请求
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @param channelCallCfg     交易映射关系
     * @throws Exception 异常
     */
    void scorePay(String discountFlag, MixedPayRequest mixedPayRequest, UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo, ChannelCallCfg channelCallCfg) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        DubboService dubboService = new DubboServiceImpl();
        OrderService orderService = new OrderServiceImpl();
        String respCode;
        String respDesc;
        int iReturnCode = 0;
        List<PayInfo> payInfoList = mixedPayRequest.getPayInfoList().stream().filter(item -> "01".equals(item.getAcctType())).collect(Collectors.toList());
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);

        //TODO 调用积分消费接口，分析调用结果
        // （1） 通讯失败或响应码非成功 ，更新订单状态为失败，调用营销冲正mompRevsal，抛出异常
        // （2） 交易成功，更新订单状态为成功（若更新订单失败，则异步调用营销冲正接口mompRevsal，并调用积分冲正服务）

    }


    void mompRevsal(String discountFlag) {
        DubboService dubboService = new DubboServiceImpl();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            List<ChannelCallCfg> mompChannelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.MOMP.getChannelType())).sorted(Comparator.comparing(ChannelCallCfg::getCallIndex)).collect(Collectors.toList());
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
            if (AppParamConstant.YES.equals(discountFlag)) {
                /*参与营销，异步调用营销冲正接口*/
                ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
                ComboPaymentRequest comboPaymentRequest = (ComboPaymentRequest) xmlTreeUtil.getXmlTreeObjectValue("comboPaymentRequest", ComboPaymentRequest.class);
                Header header = comboPaymentRequest.getHeader();
                header.setTxnNum("P02MO001");
                comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
                header.setTraceNo(sysSeqNum + (String.valueOf(Integer.parseInt(mompChannelCallCfgList.get(0).getCallIndex()) + 1)));
                comboPaymentRevsalRequest.setHeader(header);
                int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, OpmsParamConstant.DUBBO_METHOD_MOMP_REVERSAL, comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
                if (iReturnCode != 0) {
                    rglog.error("异步营销冲正服务注册失败！");
                }
            } else {
                return;
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
        }

    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item ->
                item.getBizScene().equals(ShareParamConstant.CALL_CFG_DEFAULT_BIZ_SCENE)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return transStatusEnum;
    }
}
